package com.ds;

/**
 * Created by IntelliJ IDEA.
 * User: daniel
 * Date: 28/10/2009
 * Time: 16:42:41
 */
import com.ds.tools.WebBrowser;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.event.*;
import java.io.*;
import java.util.TimerTask;
import java.util.Date;
import java.util.logging.*;
import java.security.PrivilegedAction;
import java.text.SimpleDateFormat;
import java.net.URI;
import javax.swing.*;
import javax.swing.tree.TreePath;
import javax.swing.tree.DefaultTreeModel;
import javax.xml.bind.JAXBException;


public class RSSTorrentFinder extends JFrame implements Trayable {

    private static final long serialVersionUID = 5921120740024817545L;
    private static Logger logger = Logger.getLogger("rsstorrent");
    private static SimpleDateFormat dateformat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss ");
    private static final String FRAME_TITLE = "Torrent Episodes Finder";

    private Shows shows;
    private JTree tree;
    private MyEpisodesView mev;

    private static final long ONE_HOUR = 1000L * 60 * 60;
    private static final long RELOAD_INTERVAL = ONE_HOUR * 12;

    public static void main(String[] args) throws JAXBException, FileNotFoundException {

        RSSTorrentFinder app = new RSSTorrentFinder();
        app.initLogger();
        app.scheduleReload();
    }

    private void initLogger() {
        String logFilename = "rss.log";

        // Send logger output to our FileHandler.
        Formatter frmt = new Formatter() {
            public synchronized String format(LogRecord record) {
                return dateformat.format(new Date())
                        + record.getMessage()
                        + java.security.AccessController.doPrivileged(new PrivilegedAction<Object>() {
                            public Object run() {
                                return System.getProperty("line.separator");
                            }
                        }
                );
            }
        };

        try {

            FileHandler fh = new FileHandler(logFilename);

            fh.setFormatter(frmt);
            fh.setLevel(Level.ALL);

            ConsoleHandler ch = new ConsoleHandler();
            ch.setFormatter(frmt);
            ch.setLevel(Level.ALL);

            logger.setUseParentHandlers(false);
            logger.addHandler(fh);
            logger.addHandler(ch);
            logger.setLevel(Level.ALL);

        } catch (IOException e) {
            logger.severe("initLogger: error on init logger : " + e.getMessage());

            final Writer eResult = new StringWriter();
            final PrintWriter printWriter = new PrintWriter(eResult);
            e.printStackTrace(printWriter);
            logger.severe(eResult.toString());

        }

    }


    public RSSTorrentFinder() {
        super(FRAME_TITLE);

        new RSSTrayIcon(this);
        setDefaultCloseOperation(JFrame.ICONIFIED);

        Container content = getContentPane();
        tree = new JTree(shows);

        tree.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent me) {
                if (me.getClickCount() == 2) {
                    TreePath path = ((JTree) me.getSource()).getSelectionPath();
                    Object o = path.getLastPathComponent();
                    if(o instanceof Episode){
                        Episode ep = (Episode) o;
                        handleItemDClick(ep);
                    }
                }
            }
        });

        JButton refresh = new JButton("Reload");
        refresh.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                reload();
            }
        });
        content.add(refresh, BorderLayout.SOUTH);    

        mev = new MyEpisodesView(this);
        content.add(new JScrollPane(mev), BorderLayout.NORTH);

        content.add(new JScrollPane(tree), BorderLayout.CENTER);
        setSize(600, 500);
        setLocation(300,100);
        setVisible(true);
    }

    public Image getTrayIcon() {
        Icon trayIcon = new ImageIcon("rss.png");
        Image img = new BufferedImage(16,16, BufferedImage.TYPE_4BYTE_ABGR);
        trayIcon.paintIcon(new Panel(), img.getGraphics(), 0, 0);
        return img;
    }

    private void init() throws JAXBException, FileNotFoundException {
        tree.removeAll();
        reloadConfig();
        refreshShowsRSSFeed();
        mev.init();
        tree.setModel(new DefaultTreeModel(shows));
    }

    private void reloadConfig() throws JAXBException, FileNotFoundException {
        TVShowsConfig showsConfig = new TVShowsConfig();
        showsConfig.unmarshal();
        shows = showsConfig.getShows();
        mev.setRssURL(shows.getMyEpisodesRSSLink());
    }

    private void handleItemDClick(Episode ep) {

        //show the user a waiting message
        final JDialog jd = new JDialog(this,true);
        jd.setUndecorated(true);
        JLabel label = new JLabel("Downloading torrent...");
        label.setFont(new Font("Tahoma",Font.BOLD,20));
        jd.add(label);
        int sizeX = 250;
        int sizeY = 40;
        jd.setSize(sizeX,sizeY);
        Dimension dim = getSize();
        jd.setLocation( ((int)getLocation().getX()) + (dim.width - sizeX)/2,
                ((int)getLocation().getY()) + (dim.height - sizeY)/2);

        handleTorrentRequest(jd,ep);

        //this will block the current thread until the second finishes
        jd.setVisible(true);
    }

    private void handleTorrentRequest(final JDialog jd, final Episode ep) {
        logger.info("start download torrent in seperate thread. episode " + ep.getTitle());

        new Thread(new Runnable(){
            public void run() {
                try {

                    logger.info("request to download item: " + ep.getTitle());

                    String html = WebBrowser.retrievePage(ep.getLink());

                    //the link is to an html page in torrentz.com which lists of the available torrents,
                    //we want to download the content of the page and then search for mininova torrent links
                    String torrentLink = WebBrowser.getMininovaLink(html);

                    if(torrentLink == null) {
                        torrentLink = WebBrowser.getBTJunkieLink(html);
                    }

                    if(torrentLink == null) {
                        torrentLink = WebBrowser.getBT_ChatLink(html);
                    }

                    if(torrentLink == null) {
                        logger.info("cannot extract torrent link. no supported websites found at " + ep.getLink());
                        JOptionPane.showMessageDialog(null,
                                "RSSTorrentFinder was unable to find supported torrent link. " +
                                "\nyou can find alternative link by browsing to: \n"+
                                ep.getLink(),
                                "No torrent link found",
                                JOptionPane.INFORMATION_MESSAGE);

                        java.awt.Desktop.getDesktop().browse(new URI(ep.getLink()));
                        jd.setVisible(false);
                        return;
                    }
                    logger.info("torrent link extracted: " + torrentLink);

                    File file = TorrentHandler.downloadTorrentFile(torrentLink, "torrents");
                    logger.info("torrent file downloaded: " + file.getAbsolutePath());

//                    TorrentHandler.execTorrent(file);
                    logger.info("Torrent \""+file.getAbsolutePath()+"\" executed.");

                    jd.setVisible(false);
                    setTitle(FRAME_TITLE);
                } catch (Exception e) {
                    jd.setVisible(false);
                    setTitle("Error : " + e.getMessage() );
                    JOptionPane.showMessageDialog(RSSTorrentFinder.this,
                            "RSSTorrentFinder was unable to download torrent " + ep.getTitle(),
                            "Error: " + e.getMessage(),
                            JOptionPane.ERROR_MESSAGE);
                    logStackTrace(e);
                }
            }
        }).start();
    }

    private void logStackTrace(Exception e) {
        final Writer eResult = new StringWriter();
        final PrintWriter printWriter = new PrintWriter(eResult);
        e.printStackTrace(printWriter);
        logger.severe("RSSTorrentFinder error: " + e.getMessage());
        logger.severe(eResult.toString());
    }

    private void refreshShowsRSSFeed() {
        shows.readRSSFeed(true);
    }

    public void iconClicked() {
        boolean visible = isVisible();
        setVisible(!visible);
    }

    public String getTitle() {
        return super.getTitle();
    }

    private void reload() {
        final JDialog jd = new JDialog(this,true);
        jd.setUndecorated(true);
        JLabel label = new JLabel("Reloading RSS Feeds...");
        label.setFont(new Font("Tahoma",Font.BOLD,20));
        jd.add(label);
        int sizeX = 250;
        int sizeY = 40;
        jd.setSize(sizeX,sizeY);
        Dimension dim = getSize();
        jd.setLocation( ((int)getLocation().getX()) + (dim.width - sizeX)/2,
                ((int)getLocation().getY()) + (dim.height - sizeY)/2);

        new Thread(new Runnable(){
            public void run() {
                try {
                    init();
                } catch (Exception e) {
                    setTitle("Error : " + e.getMessage() );
                    JOptionPane.showMessageDialog(RSSTorrentFinder.this,
                            "RSSTorrentFinder was unable to load RSS feeds.",
                            "Error: " + e.getMessage(),
                            JOptionPane.ERROR_MESSAGE);
                    e.printStackTrace();
                }
                finally {
                    jd.setVisible(false);
                }
            }
        }).start();

        jd.setVisible(true);
    }

    private void scheduleReload() {
        java.util.Timer reloader = new java.util.Timer();
        reloader.schedule(new TimerTask(){
            public void run() {
                reload();
                Date nextRun = new Date(System.currentTimeMillis() + RELOAD_INTERVAL);
                logger.info("Next reload will run at " + dateformat.format(nextRun) );
            }
        }, 0, RELOAD_INTERVAL);
    }


}
